# coding=utf-8
import os
import platform
import time
import uuid
# import tkinter
# from tkinter import *
from hk.hc_net_sdk import *
from datetime import datetime
import requests
import json
# 系统环境标识
WINDOWS_FLAG = True
from flask import Flask,request,jsonify
# 报警信息列表，报一次在回调中加1次记录
alarm_info = []
server = Flask(__name__)
# 获取当前系统环境
def GetPlatform():
    sysstr = platform.system()
    print('' + sysstr)
    if sysstr != "Windows":
        global WINDOWS_FLAG
        WINDOWS_FLAG = False

# 设置SDK初始化依赖库路径
def SetSDKInitCfg(sdk):
    # 设置HCNetSDKCom组件库和SSL库加载路径
    # print(os.getcwd())    
    if WINDOWS_FLAG:
        strPath = os.getcwd().encode('gbk')
        sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()
        sdk_ComPath.sPath = strPath
        sdk.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
        sdk.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'\libcrypto-1_1-x64.dll'))
        sdk.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'\libssl-1_1-x64.dll'))
    else:
        strPath = os.getcwd().encode('utf-8')
        sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()
        sdk_ComPath.sPath = strPath
        sdk.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))
        sdk.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'/libcrypto.so.1.1'))
        sdk.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'/libssl.so.1.1'))

class NET_DVR_BARRIERGATE_CFG(Structure):
    _fields_ = [
        ("dwSize", c_uint32),
        ("dwChannel", c_uint32),  # 通道号
        ("byLaneNo", c_ubyte),  # 道闸号（0-表示无效值(设备需要做有效值判断),1-道闸1）
        ("byBarrierGateCtrl", c_ubyte),  # 0-关闭道闸,1-开启道闸,2-停止道闸 3-锁定道闸,4~解锁道闸
        ("byEntranceNo", c_ubyte),  # 出入口编号 [1,8]
        ("byUnlock", c_ubyte),  # 启用解锁使能，0~为不启用，1~启用
        ("byRes", c_ubyte * 12)
    ]

# 开闸
def cate_control():
    try:
        jsons = request.json
        if jsons.__contains__('ip') and jsons.__contains__('user_name') and jsons.__contains__('password'):
            # 设备ip
            ip = jsons['ip']
            # 设备用户名
            user_name = jsons['user_name']
            # 设备登录密码
            password = jsons['password']
            if ip is None or ip == '':return jsonify(code=1,msg="ip不能为空!")
            if user_name is None or user_name == '':return jsonify(code=1,msg="user_name不能为空!")
            if password is None or password == '':return jsonify(code=1,msg="password不能为空!")
            # 获取系统平台
            GetPlatform()
            # 加载库,先加载依赖库
            if WINDOWS_FLAG:
                #os.chdir(r'./lib/win')
                #os.chdir('D:\ideaworkspace\python_iot\python\gatewaybox\hk\lib\win')
                os.chdir('/mnt/work/python/gatewaybox/hk/lib/win')
                sdk = ctypes.CDLL(r'./HCNetSDK.dll')
            else:
                #os.chdir(r'./lib/linux')
                os.chdir('/mnt/work/python/gatewaybox/hk/lib/linux')
                sdk = cdll.LoadLibrary(r'./libhcnetsdk.so')

            SetSDKInitCfg(sdk)  # 设置组件库和SSL库加载路径

            # 初始化
            sdk.NET_DVR_Init()
            # 启用SDK写日志
            sdk.NET_DVR_SetLogToFile(3, bytes('../../log/SdkLog_Python/', encoding="utf-8"), False)

            # 通用参数配置
            sdkCfg = NET_DVR_LOCAL_GENERAL_CFG()
            sdkCfg.byAlarmJsonPictureSeparate = 1
            sdk.NET_DVR_SetSDKLocalCfg(17, byref(sdkCfg))

            # 初始化用户id, 在调用正常是程序一般返回正数，故初始化一个负数
            UserID = c_long(-1)

            # 用户注册设备
            # c++传递进去的是byte型数据，需要转成byte型传进去，否则会乱码
            # 登录参数，包括设备地址、登录用户、密码等
            struLoginInfo = NET_DVR_USER_LOGIN_INFO()
            struLoginInfo.bUseAsynLogin = 0  # 同步登录方式
            struLoginInfo.sDeviceAddress = bytes(ip, "ascii")  # 设备IP地址
            struLoginInfo.wPort = 8000  # 设备服务端口
            struLoginInfo.sUserName = bytes(user_name, "ascii")  # 设备登录用户名
            struLoginInfo.sPassword = bytes(password, "ascii")  # 设备登录密码
            struLoginInfo.byLoginMode = 0

            # 设备信息, 输出参数
            struDeviceInfoV40 = NET_DVR_DEVICEINFO_V40()

            UserID = sdk.NET_DVR_Login_V40(byref(struLoginInfo), byref(struDeviceInfoV40))
            if UserID < 0:
                print("Login failed, error code: %d" % sdk.NET_DVR_GetLastError())
                sdk.NET_DVR_Cleanup()
            else:
                print("UserID %s" % UserID)
                print('登录成功，设备序列号：%s' % str(struDeviceInfoV40.struDeviceV30.sSerialNumber, encoding = "utf8"))

            struGateCfg = NET_DVR_BARRIERGATE_CFG()
            struGateCfg.dwSize = sizeof(struGateCfg)
            struGateCfg.dwChannel = 1  # 通道号
            struGateCfg.byLaneNo = 1  # 道闸号
            struGateCfg.byBarrierGateCtrl = 1  # 控制参数：0- 关闭道闸，1- 开启道闸，2- 停止道闸，3- 锁定道闸，4- 解锁道闸
            struGateCfg.byEntranceNo = 1  # 出入口编号
            struGateCfg.byUnlock = 0  # 启用解锁使能

            bCtrl = sdk.NET_DVR_RemoteControl(UserID, 3128, byref(struGateCfg), sizeof(struGateCfg))
            if bCtrl == False:
                print("NET_DVR_RemoteControl 失败, error code: %d" % sdk.NET_DVR_GetLastError())
        else:
            return jsonify(code=1,msg="缺少必要参数ip、user_name、password")
    except Exception as e:
        print(e)
        return jsonify(
            code=1,
            msg="Server internal error"
        )
    return jsonify(
        code=0,
        msg="success"
    )
# 开闸自动
def cate_control_auto(ip,user_name,password):
    try:
        if ip is None or ip == '':return jsonify(code=1,msg="ip不能为空!")
        if user_name is None or user_name == '':return jsonify(code=1,msg="user_name不能为空!")
        if password is None or password == '':return jsonify(code=1,msg="password不能为空!")
        # 获取系统平台
        GetPlatform()
        # 加载库,先加载依赖库
        if WINDOWS_FLAG:
            #os.chdir(r'./lib/win')
            #os.chdir('D:\ideaworkspace\python_iot\python\gatewaybox\hk\lib\win')
            os.chdir('/mnt/work/python/gatewaybox/hk/lib/win')
            sdk = ctypes.CDLL(r'./HCNetSDK.dll')
        else:
            #os.chdir(r'./lib/linux')
            os.chdir('/mnt/work/python/gatewaybox/hk/lib/linux')
            sdk = cdll.LoadLibrary(r'./libhcnetsdk.so')

        SetSDKInitCfg(sdk)  # 设置组件库和SSL库加载路径

        # 初始化
        sdk.NET_DVR_Init()
        # 启用SDK写日志
        sdk.NET_DVR_SetLogToFile(3, bytes('../../log/SdkLog_Python/', encoding="utf-8"), False)

        # 通用参数配置
        sdkCfg = NET_DVR_LOCAL_GENERAL_CFG()
        sdkCfg.byAlarmJsonPictureSeparate = 1
        sdk.NET_DVR_SetSDKLocalCfg(17, byref(sdkCfg))

        # 初始化用户id, 在调用正常是程序一般返回正数，故初始化一个负数
        UserID = c_long(-1)

        # 用户注册设备
        # c++传递进去的是byte型数据，需要转成byte型传进去，否则会乱码
        # 登录参数，包括设备地址、登录用户、密码等
        struLoginInfo = NET_DVR_USER_LOGIN_INFO()
        struLoginInfo.bUseAsynLogin = 0  # 同步登录方式
        struLoginInfo.sDeviceAddress = bytes(ip, "ascii")  # 设备IP地址
        struLoginInfo.wPort = 8000  # 设备服务端口
        struLoginInfo.sUserName = bytes(user_name, "ascii")  # 设备登录用户名
        struLoginInfo.sPassword = bytes(password, "ascii")  # 设备登录密码
        struLoginInfo.byLoginMode = 0

        # 设备信息, 输出参数
        struDeviceInfoV40 = NET_DVR_DEVICEINFO_V40()

        UserID = sdk.NET_DVR_Login_V40(byref(struLoginInfo), byref(struDeviceInfoV40))
        if UserID < 0:
            print("Login failed, error code: %d" % sdk.NET_DVR_GetLastError())
            sdk.NET_DVR_Cleanup()
        else:
            print("UserID %s" % UserID)
            print('登录成功，设备序列号：%s' % str(struDeviceInfoV40.struDeviceV30.sSerialNumber, encoding = "utf8"))

        struGateCfg = NET_DVR_BARRIERGATE_CFG()
        struGateCfg.dwSize = sizeof(struGateCfg)
        struGateCfg.dwChannel = 1  # 通道号
        struGateCfg.byLaneNo = 1  # 道闸号
        struGateCfg.byBarrierGateCtrl = 1  # 控制参数：0- 关闭道闸，1- 开启道闸，2- 停止道闸，3- 锁定道闸，4- 解锁道闸
        struGateCfg.byEntranceNo = 1  # 出入口编号
        struGateCfg.byUnlock = 0  # 启用解锁使能

        bCtrl = sdk.NET_DVR_RemoteControl(UserID, 3128, byref(struGateCfg), sizeof(struGateCfg))
        if bCtrl == False:
            print("NET_DVR_RemoteControl 失败, error code: %d" % sdk.NET_DVR_GetLastError())
    except Exception as e:
        print(e)
